package cn.com.obs;


import cn.com.bean.ResultResponse;
import cn.com.obs.entity.ClusterSubAccountRespDto;
import cn.com.obs.entity.ObsEntityPageReq;
import cn.com.obs.entity.ObsEntityRep;
import cn.com.utils.HttpClientUtil;
import cn.hutool.json.JSONUtil;
import com.obs.services.model.HttpMethodEnum;
import io.minio.admin.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import software.amazon.awssdk.services.s3.S3Client;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

@Slf4j
public class S3UtilsTest {

    public static final String ACCESS_KEY = "et4AyzzgmstKkvsHSHlI";

    public static final String SECRET_KEY = "XglPajavcwudGWgm5bnQCfgT5GElgI2ZoeVM9oZW";

    public static final String OBS_URL = "https://10.106.3.111:32296";

    public static final String BUCKET_NAME = "bssadmin-sub";

    public static ClusterSubAccountRespDto mockAccount = new ClusterSubAccountRespDto();

    static {
        mockAccount.setAccessKey(ACCESS_KEY);
        mockAccount.setSecretKey(SECRET_KEY);
        mockAccount.setObsUrl(OBS_URL);
        mockAccount.setBucketName(BUCKET_NAME);
    }

    @Test
    public void testGetS3Client() {
        //mockAccount.setAccessKey("admin");
        //mockAccount.setSecretKey("adminminio");
        //mockAccount.setObsUrl("http://127.0.0.1:9000");
        mockAccount.setObsUrl("https://10.106.3.111:32296");
        spikSsl();

        S3Client s3Client = S3Utils.getS3Client(mockAccount);

        assertNotNull(s3Client);
    }

    @Test
    public void testCreateFolder() {

        boolean result = S3Utils.createFolder(mockAccount, "testFolder", "SLURM");
        assertTrue(result);

    }


    private S3Client verify(S3Client mockS3Client) {
        if (mockS3Client == null) {
            throw new IllegalArgumentException("mockS3Client cannot be null");
        }
        return mockS3Client;
    }

    //测试桶创建
    @Test
    public void testCreateBucket() {
        S3Utils.createBucket(mockAccount, "S1LURM", "user003-bucket");
    }

    //测试设置桶策略
    @Test
    public void testSetBucketPolicy() {
        // 存储桶策略
        String bucketPolicy = "{" +
                "  \"Version\": \"2012-10-17\"," +
                "  \"Statement\": [" +
                "    {" +
                "      \"Sid\": \"AddPerm\"," +
                "      \"Effect\": \"Allow\"," +
                "      \"Principal\": {\"AWS\": \"arn:aws:iam::user003:root\"}," +
                "      \"Action\": [" +
                "        \"s3:GetObject\"," +
                "        \"s3:PutObject\"" +
                "      ]," +
                "      \"Resource\": [\"arn:aws:s3:::\" + bucketName + \"/*\"]" +
                "    }" +
                "  ]" +
                "}";
        S3Utils.setBucketPolicy(mockAccount, "user003-bucket", bucketPolicy);
    }

    //测试桶删除
    @Test
    public void testDeleteBucket() {
        S3Utils.deleteBucket(mockAccount, "SLURM", "my-bucket");
    }

    // 测试文件删除
    @Test
    public void testDeleteFile() {
        boolean b = S3Utils.deleteObject(mockAccount, Collections.singletonList("testFolder/image.jpg"), "SLURM");
        assertTrue(b);

    }

    //测试文件查看
    @Test
    public void testFileViewing() {
        ObsEntityPageReq pageReq = new ObsEntityPageReq();
        pageReq.setPrefix("");
        pageReq.setMarker("");
        pageReq.setMaxKeys(10);
        mockAccount.setAccessKey("user003");
        mockAccount.setSecretKey("kx4W3JK%ZZTvI5VWiT!^QvtG");
        mockAccount.setBucketName("my-bucket");
        ObsEntityRep slurm = S3Utils.listObjects(pageReq, mockAccount, "SL1URM");
        System.out.println(slurm);
    }


    //测试临时凭证上传的使用
    @Test
    public void testTemporaryCredentials() {

        String presignedUrl = S3Utils.getObsTemporaryVoucher(mockAccount, "testFolder/image.jpg", null, HttpMethodEnum.PUT.getOperationType());
        try {
            log.info("presignedUrl: " + presignedUrl);
            spikSsl();
            URL url = new URL(presignedUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("PUT");
            connection.setDoOutput(true);
            // 上传文件内容
            try (InputStream inputStream = Files.newInputStream(
                    Paths.get("E:\\cloud_star\\240108浦发银行项目\\aksk 接口\\Ak_SK_demo\\Ak_SK_demo\\src\\main\\resources\\img\\640.jpg"));
                 OutputStream outputStream = connection.getOutputStream()) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                System.out.println("File uploaded successfully!");
            } else {
                System.out.println("File upload failed. Response code: " + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //测试临时凭证下载的使用
    @Test
    public void testTemporaryCredentialsDownload() {
        String presignedUrl = S3Utils.getObsTemporaryVoucher(mockAccount, "testFolder/image.jpg", null, HttpMethodEnum.GET.getOperationType());
        try {
            log.info("presignedUrl: " + presignedUrl);
            try {
                spikSsl();
                URL url = new URL(presignedUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setDoOutput(true);
                connection.setDoInput(true);
                // 设置编码
                String encoding = "UTF-8";
                connection.setRequestProperty("Accept-Charset", encoding);
                String localFilePath = "src/main/resources/img/640_download.jpg";
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    try (InputStream inputStream = connection.getInputStream();
                         OutputStream outputStream = Files.newOutputStream(Paths.get(localFilePath))) {
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, bytesRead);
                        }
                        System.out.println("Image downloaded successfully: " + localFilePath);
                    }
                } else {
                    System.out.println("File download failed. Response code: " + responseCode);
                }
            } catch (IOException e) {
                System.out.println("Error downloading file: " + e.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static void spikSsl() {
        // 创建一个信任所有证书的 TrustManager
        TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
                }
        };
        SSLContext sc = null;

        try {
            // 创建一个忽略证书验证的 SSLContext
            sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
    }

    //测试创建策略
    @Test
    public void testCreatePolicy() {
        MinioManager minioManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);

        List<String> action = new ArrayList<>();
        action.add("arn:aws:s3:::my-bucket/*");
        action.add("arn:aws:s3:::user003-bucket/*");
        action.add("arn:aws:s3:::my-bucket1/*");
        String bucket = JSONUtil.toJsonStr(action);
        // 策略管理示例
        String policyDocument = "{\n" +
                "  \"Version\": \"2012-10-17\",\n" +
                "  \"Statement\": [\n" +
                "    {\n" +
                "      \"Effect\": \"Allow\",\n" +
                "      \"Action\": [\n" +
                "        \"s3:ListBucket\",\n" +
                "        \"s3:ListBucketMultipartUploads\",\n" +
                "        \"s3:GetBucketLocation\",\n" +
                "        \"s3:AbortMultipartUpload\",\n" +
                "        \"s3:DeleteObject\",\n" +
                "        \"s3:GetObject\",\n" +
                "        \"s3:ListMultipartUploadParts\",\n" +
                "        \"s3:PutObject\"\n" +
                "      ],\n" +
                "      \"Resource\": " + bucket + "\n" +
                "    }\n" +
                "  ]\n" +
                "}";
        minioManager.createPolicy("testPolicy", policyDocument);
    }

    //测试删除策略
    @Test
    public void testDeletePolicy() {
        MinioManager minioManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);
        minioManager.deletePolicy("testPolicy");
    }

    //测试获取策略
    @Test
    public void testGetPolicy() {
        MinioManager minioManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);
        minioManager.listPolicies();
        minioManager.getPolicy("testPolicy");
    }

    //测试获取用户信息
    @Test
    public void testGetUserInfo() {
        MinioManager minioUserInfoManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);
        UserInfo user001 = minioUserInfoManager.getUserInfo("user001");
        System.out.println(JSONUtil.toJsonStr(user001));
    }


    //测试获取用户信息
    @Test
    public void testGetUserInfoByToken() {
        MinioManager minioManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);
        Map<String, UserInfo> users = minioManager.listUsers();
        users.forEach((key, userInfo) -> {
            System.out.println("User: " + key +
                                       ", policyName: " + userInfo.policyName() +
                                       ", MemberOf: " + userInfo.memberOf() +
                                       ", AccessKey: " + key +
                                       ", Status: " + userInfo.status() +
                                       ", SecretKey: " + userInfo.secretKey());
        });
    }

    //测试创建用户
    @Test
    public void testCreateUser() {
        MinioManager minioManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);
        minioManager.createUser("user005", UserInfo.Status.ENABLED, "kx4W3JK%ZZTvI5VWiT!^QvtG",
                                "testPolicy", null);

    }

    //测试修改策略

    @Test
    public void testSetPolicy() {
        MinioManager minioManager = new MinioManager(OBS_URL, ACCESS_KEY, SECRET_KEY);
        minioManager.setPolicy("testPolicy", "user004");
    }

    //测试查询

    @Test
    public void testQuery() throws Exception {
        String url = "http://localhost:8081/service/rest/v1/search?format=docker";

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Basic YWRtaW46MXEydzNlJFI=");
        HttpClientUtil.get(url, headers);

        //生成curl方式

        String curl =
                "curl -X GET -H 'Authorization: Basic YWRtaW46MXEydzNlJFI=' 'http://localhost:8081/service/rest/v1/search/assets?format=docker'";
    }


    //接口调用测试
    @Test
    public void testInterface() throws Exception {
        //	URI： https://10.99.12.40:1099/wtzb/queryMRHomeList
        //	请求header：Authorization 值为 用户名:密码 拼接串base64编码（例如：zkr:zkr123的base64编码emtyOnprcjEyMw==），实际值请咨询接口厂商
        //	数据格式：JSON
        //	请求报文参数说明
        //字段名	描述	是否必填
        //startDate	调用开始时间	是
        //endDate	调用结束时间	是
        //pageNum	调用数据页码	是
        //pageSize	每页查询数量	是
        //bussType	业务类型
        //zybasy_xy：住院病案首页-西医
        //zybasy_zy：住院病案首页-中医
        //zybasy_jc： 住院病案首页-基层	是
        //

        //代码实现
        String url = "https://10.99.12.40:1099/wtzb/queryMRHomeList";
        String username = "zkr";
        String password = "zkr123";
        String base64Str = Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
        String authorization = "Authorization: Basic " + base64Str;
        HashMap<String, String> header = new HashMap<>();
        header.put("Authorization", authorization);
        String startDate = "2021-01-01";
        String endDate = "2021-12-31";
        String pageNum = "1";
        String pageSize = "10";
        String bussType = "zybasy_xy";
        String data = "{\n" +
                "  \"startDate\": \"" + startDate + "\",\n" +
                "  \"endDate\": \"" + endDate + "\",\n" +
                "  \"pageNum\": \"" + pageNum + "\",\n" +
                "  \"pageSize\": \"" + pageSize + "\",\n" +
                "  \"bussType\": \"" + bussType + "\"\n" +
                "}";
        ResultResponse result = HttpClientUtil.post(url, header, data);
        System.out.println(result);
    }
}
